#pragma once
#ifndef HTTP_REQ_H

#define HTTP_REQ_H

#include "AbstractIRequest.h"
#include "AbstractHTTPServer.h"
#include "IOCPNetwork.h"
#include "HighResolutionTimer.h"
#include "MemoryOperator.h"
/*
 http请求类
*/
class HTTPRequest :
	public AbstractIRequest
{
public:
	 ~HTTPRequest();

	 HTTPRequest(AbstractHTTPServer *, IOCPNetwork *);

	/* 访问属性 */
	 void* getConnectionId();
	 unsigned long getTotalRecvBytes();
	 HTTPMethod method();
	 std::string uri(bool decode);
	 std::string field(const char* key);
	 bool keepAlive();
	 bool range(__int64 &from, __int64 &to);
	 bool isValid();
	 unsigned long  headerSize();
	 unsigned long  size();
	 unsigned long  contentLength();
	 __int64 startTime();

	/* 返回请求头 */
	 std::string getHeader();

	/* 读取 POST DATA */
	 size_t read(unsigned char * buf, size_t len);
	 bool eof();

	/* 控制运行 */
	 int run(void * connId, void* clientSock, unsigned long timeout);
	 bool stop(int ec);
	 bool reset();

protected:

	 /*
	   NO.1 客户端socket
	   NO.2 完成端口状态标记
	   NO.3 是否记录发送的字节数
	   NO.3 发送的字节数
	   NO.4 缓冲区
	   NO.5 缓冲区长度
	   NO.6 参数
	 */
	 static void RequestCallBack(iocpKey k, int flags, bool result, int transfered, byte* buf, size_t len, void* param);

	 /*接收数据*/
	 void onRecive(size_t flags, byte lpNumberOfBytesRecvd);

	 /*
	  关闭了连接
	  NO.1 退出代码
	 */
	 void close(int exitCode);

	 // 套接字收到数据后,推入到 HTTP Request 实例中.
	 int push(const byte * data, unsigned int len);

	 /*获取内容长度*/
	 std::string getField(const char *field);

	 size_t getContentLenth();


	 /*删除socket缓冲区*/
	 void deleteSocketBuff();

private:
	AbstractHTTPServer *server;

	// 输入输出命令行端口对象
	IOCPNetwork * iocp;

	// 客户端 socket
	void * clientSocket;

	// 客户端socket缓冲区
	byte * clientSocketBuff;

	//客户端缓冲区长度
	unsigned int clientSocketLength;

	// 连接对象
	void * connection;

	// 总共接收了多少数据
	size_t totalReceiveNumber;

	// 开始处理的时间
	__int64 starParsetTime;

	/*header信息*/
	MemoryOperator<byte> headerData;
	
	/*post数据*/
	MemoryOperator<byte> *postData;

	/**
	 * 高精度时间
	 */
	HighResolutionTimer timer;

	// header 信息是否已接收
	bool isHeadReceive;

	/*header 内容长度*/
	size_t contentLengths;

};

#endif // !HTTP_REQ_H